package interfaceusuario;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.LinkedList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;

import propertieslinguagem.SingletonSetaLinguagemEArmazenaResourceBundle;

import dao.FachadaAcessoConfiguracoesSistema;

import salvarcasodetestes.DadosProjetoDeTestesComMain;
import salvarcasodetestes.FachadaParaDadosDeSuitesDeTestes;
import entidadesparaguardardadosteste.CasoDeTeste;

public class TelaResultadosDosTestesEmTabelaParaTestarMain implements ActionListener
{
	private LinkedList<CasoDeTeste> casosDeTeste;
	private HashMap<CasoDeTeste,Object> casosDeTesteERetornosAposExecucao;
	@SuppressWarnings("unused")
	private HashMap<CasoDeTeste, Boolean> casosDeTesteESeEleConseguiuSerExecutado;
	private JButton botaoSalvarTesteCriado;
	private JButton botaoVoltarAoMenuPrincipal;
	private String nomeSuiteDeTestes;
	private int quantasVariaveisCriadasParaSubstituirLeituraDoTeclado;
	private int quantasVariaveisCriadasParaSubstituirEscritaNoTerminal; 
	
	
	/*cada linha da tabela representa um conjunto de varios casos de uso para setar valores p 
	 *variaveis de leitura do teclado e gets() de variaveis de escrita no terminal. 
	 *Enfim, cada linha representa uma vez que o usuario preencheu todos os formularios da pagina
	 *anterior e terminou de criar o teste. Vamos sair preenchendo essa linkedList a medida
	 *que formos lendo os casos de uso e quando essa linkedlist tiver 
	 *tamanho =  quantasVariaveisCriadasParaSubstituirLeituraDoTeclado + quantasVariaveisCriadasParaSubstituirEscritaNoTerminal +
	 *quantasVariaveisCriadasParaSubstituirEscritaNoTerminal (ja que sao os resultados obtidos e os esperados),
	 *ela voltara a ser uma linkedlist vazia e mais uma linha da tabela com os resultados do
	 *teste serah criada
	 * */
	private LinkedList<Object> valoresEntradas;
	private LinkedList<Object> saidasEsperadas;
	private LinkedList<Object> saidasObtidas;
	
	private JFrame janelaResultadosDosTestes;
	
	private LinkedList<JTable> tabelasComResultadosDosTestes;
	private LinkedList<DefaultTableModel> modelosDasTabelasCriadas;
	
	private DadosProjetoDeTestesComMain projetoDeTestesCriadoPeloUsuario;
	
	public TelaResultadosDosTestesEmTabelaParaTestarMain(LinkedList<CasoDeTeste> casosDeTeste,
			HashMap<CasoDeTeste,Object> casosDeTesteERetornosAposExecucao,
			HashMap<CasoDeTeste, Boolean> casosDeTesteESeEleConseguiuSerExecutado, DadosProjetoDeTestesComMain dadosProjetoDeTestes,
			int quantasVariaveisCriadasParaSubstituirLeituraDoTeclado, 
			int quantasVariaveisCriadasParaSubstituirEscritaNoTerminal,
			JFrame janelaPrincipalTestable)
	{
		this.casosDeTeste = casosDeTeste;
		this.casosDeTesteERetornosAposExecucao = casosDeTesteERetornosAposExecucao;
		this.casosDeTesteESeEleConseguiuSerExecutado = casosDeTesteESeEleConseguiuSerExecutado;
		
		SingletonSetaLinguagemEArmazenaResourceBundle conheceLinguagemDoSistema = 
				SingletonSetaLinguagemEArmazenaResourceBundle.getInstance();
		String tituloJanelaResultados = conheceLinguagemDoSistema.getString("janelaResultadosDosTestesTelaResultadosDosTestesEmTabelaParaTestarMain");
		
		this.janelaResultadosDosTestes = janelaPrincipalTestable;
		this.janelaResultadosDosTestes.setTitle(tituloJanelaResultados);
		this.nomeSuiteDeTestes = dadosProjetoDeTestes.getNomeProjetoDeTestes();
		
		this.tabelasComResultadosDosTestes = new LinkedList<JTable>();
		this.modelosDasTabelasCriadas = new LinkedList<DefaultTableModel>();
		
		this.quantasVariaveisCriadasParaSubstituirEscritaNoTerminal = quantasVariaveisCriadasParaSubstituirEscritaNoTerminal;
		this.quantasVariaveisCriadasParaSubstituirLeituraDoTeclado = quantasVariaveisCriadasParaSubstituirLeituraDoTeclado;
		
		valoresEntradas = new LinkedList<Object>();
		saidasEsperadas = new LinkedList<Object>();
		saidasObtidas = new LinkedList<Object>();
		
		this.projetoDeTestesCriadoPeloUsuario = dadosProjetoDeTestes;
	}
	
	public void mostrarCasosDeTeste()
	{
		for(int i = 0; i < this.casosDeTeste.size(); i++)
		{
			CasoDeTeste umCaso = this.casosDeTeste.get(i);
			System.out.println("testando o caso de teste " + umCaso.getMetodo().getCabecalhoDoMetodo());
			LinkedList<Object> parametros = umCaso.getValoresDosParametrosDoMetodo();
			System.out.println("parametros:");
			for(int j = 0; j < parametros.size(); j++)
			{
				System.out.println(parametros.get(j));
			}
			
			if(umCaso.getValorEsperadoDaSaida() != null)
			{
				System.out.println("valor esperado para saida:" + umCaso.getValorEsperadoDaSaida());
			}
			
			if(this.casosDeTesteERetornosAposExecucao.get(umCaso) != null)
			System.out.println("valor obtido para saida:" + this.casosDeTesteERetornosAposExecucao.get(umCaso));
		}
	}
	
	public void desenharTelaResultadosDosTestes()
	{
		CriaPainelDeFundoComBackground criadorPainelPadrao = CriaPainelDeFundoComBackground.getInstance();
		JPanel painelImagemFundo =
				criadorPainelPadrao.criarPainelDeFundoPadraoDoSistema();
		
		//primeiro vamos criar somente um jpanel com o titulo da tela
		
		SingletonSetaLinguagemEArmazenaResourceBundle conheceLinguagemDoSistema = 
				SingletonSetaLinguagemEArmazenaResourceBundle.getInstance();
		String tituloLabelTitulo = conheceLinguagemDoSistema.getString("labelTituloTelaResultadosDosTestesEmTabelaParaTestarMain");
		
		JLabel labelTitulo = CriadorTextLabel.criarTextlabel(tituloLabelTitulo, 20);
		JPanel painelTitulo = criadorPainelPadrao.criarPainelDeFundoPadraoDoSistema();
		
		painelTitulo.add(labelTitulo);
		
		
		GridBagLayout layout = new GridBagLayout();
		painelImagemFundo.setLayout(layout);
		GridBagConstraints grid = new GridBagConstraints();
		
		
		//adicionaremos o titulo ao painel principal e gigante da tela
		grid.gridheight = 1;
		grid.gridy = 0;
		grid.insets = new Insets(0,0,0,0);
		painelImagemFundo.add(painelTitulo,grid);
		
		//agora criaremos as tabelas com todos os resultados de casos de testes
		criarTabelasComTodosOsResultadosDosTestes();
		
		String tituloBotaoSalvar = conheceLinguagemDoSistema.getString("botaoSalvarTesteCriadoTelaResultadosDosTestesEmTabelaParaTestarMain");
		
		this.botaoSalvarTesteCriado = new JButton(tituloBotaoSalvar);
		this.botaoSalvarTesteCriado.addActionListener(this);
		
		String tituloBotaoVoltar = conheceLinguagemDoSistema.getString("botaoVoltarAoMenuPrincipalTelaResultadosDosTestesEmTabelaParaTestarMain");
		this.botaoVoltarAoMenuPrincipal = new JButton(tituloBotaoVoltar);
		this.botaoVoltarAoMenuPrincipal.addActionListener(this);
		
		JPanel painelBotoesNoFundoDaTela = criadorPainelPadrao.criarPainelDeFundoPadraoDoSistema();
		
		painelBotoesNoFundoDaTela.add(botaoSalvarTesteCriado);
		painelBotoesNoFundoDaTela.add(botaoVoltarAoMenuPrincipal);
		
		
		//agora, criar o painel com a juncao de todas as tabelas:
		JScrollPane painelComResultadosDosTestes = this.criarPainelComTodosOsResultadosCasosDeTeste();
		
		grid.gridheight = 7;
		grid.gridy = 1;
		painelImagemFundo.add(painelComResultadosDosTestes,grid);
		grid.gridheight = 1;
		grid.gridy = 8;
		painelImagemFundo.add(painelBotoesNoFundoDaTela, grid);
		
		this.colorirTodasAsColunasDeTodasAsTabelasQueForemNecessarias();
		
		
	
		janelaResultadosDosTestes.getContentPane().add(painelImagemFundo);
		
		
		janelaResultadosDosTestes.getContentPane().revalidate();
		janelaResultadosDosTestes.getContentPane().setVisible(true);
	}
	
	private void criarTabelasComTodosOsResultadosDosTestes()
	{
		for(int i = 0; i < this.casosDeTeste.size(); i++)
		{
				CasoDeTeste umCasoDeTeste = this.casosDeTeste.get(i);
				String cabecalhoDoMetodoEmUmCasoDeTeste = umCasoDeTeste.getMetodo().getCabecalhoDoMetodo();
				if(this.modelosDasTabelasCriadas.size() >= 1)
				{
					/*ja temos uma tabela para inserir valores, nao precisamos criar outra*/
					 
					//primeiro pegarei o modelo da unica tabela criada
					DefaultTableModel modeloDaUltimaTabelaCriada = 
										this.modelosDasTabelasCriadas.getLast();
					
					//agora vou preparar a insercao do caso de teste na tabela
					if(cabecalhoDoMetodoEmUmCasoDeTeste.contains("main") == false)
					{
						inserirCasoDeTesteEmTabelaJaExistente(modeloDaUltimaTabelaCriada, umCasoDeTeste);
					}
				}
				else
				{
					if(cabecalhoDoMetodoEmUmCasoDeTeste.contains("main") == false)
					{
						//os metodos main nao serao adicionados a tabela
						criarNovaTabelaEInserirCasoDeTesteNela(umCasoDeTeste);
					}
				}
		}
	}
	
	private void criarNovaTabelaEInserirCasoDeTesteNela(CasoDeTeste casoDeTeste)
	{
		DefaultTableModel modelo = new DefaultTableModel();
		JTable tabela = new JTable(modelo);
		modelo = definirCabecalhosDaTabela(modelo);
		inserirResultadosDoTesteNaTabela(modelo, casoDeTeste);
		
		this.tabelasComResultadosDosTestes.add(tabela);
		this.modelosDasTabelasCriadas.add(modelo);
	}
	
	private void inserirCasoDeTesteEmTabelaJaExistente(DefaultTableModel modeloDaTabela, CasoDeTeste casoDeTeste)
	{
		//so precisamos do modelo da tabela para inserir uma nova linha na tabela
		inserirResultadosDoTesteNaTabela(modeloDaTabela, casoDeTeste);
	}
	
	
	private DefaultTableModel definirCabecalhosDaTabela(DefaultTableModel modelo)
	{
		SingletonSetaLinguagemEArmazenaResourceBundle conheceLinguagemDoSistema = 
				SingletonSetaLinguagemEArmazenaResourceBundle.getInstance();
		
		//primeiro as colunas para as variaveis de entrada
		for(int i = 0; i < this.quantasVariaveisCriadasParaSubstituirLeituraDoTeclado; i++)
		{
			String tituloVariavelEntrada = conheceLinguagemDoSistema.getString("variavelEntradaTelaResultadosDosTestesEmTabelaParaTestarMain");
			modelo.addColumn(tituloVariavelEntrada + i);
		}
		
		for(int j = 0; j < this.quantasVariaveisCriadasParaSubstituirEscritaNoTerminal; j++)
		{
			String tituloVariavelSaida = conheceLinguagemDoSistema.getString("variavelSaidaTelaResultadosDosTestesEmTabelaParaTestarMain");
			String tituloValorObtido = conheceLinguagemDoSistema.getString("valorObtidoTelaResultadosDosTestesEmTabelaParaTestarMain");
			
			modelo.addColumn(tituloVariavelSaida + j);
			modelo.addColumn(tituloValorObtido + j);
		}
		return modelo;
	}
	
	
	
	private void inserirResultadosDoTesteNaTabela(DefaultTableModel modelo, CasoDeTeste casoDeTeste)
	{
		//primeiro iremos pegar os dados que precisarmos para formar a tabela
		System.out.println("verificando metodo antes de inserir na tabela:" + casoDeTeste.getMetodo().getCabecalhoDoMetodo());
		
		LinkedList<Object> valoresDosParametrosDoMetodo = 
				casoDeTeste.getValoresDosParametrosDoMetodo();
		
		Object resultadoObtido = null;
		Object resultadoEsperado = null;
		
		if(casoDeTeste.getMetodoAssociadoPossuiRetorno() == true &
				this.casosDeTesteERetornosAposExecucao.get(casoDeTeste) != null)
		{
			resultadoObtido = this.casosDeTesteERetornosAposExecucao.get(casoDeTeste);
			System.out.println("resultado obtido:" + resultadoObtido);
		}
		
		if(casoDeTeste.getMetodoAssociadoPossuiRetorno() == true)
		{
			resultadoEsperado = casoDeTeste.getValorEsperadoDaSaida();
			System.out.println("resultado esperado:" + resultadoEsperado);
		}
		
		//agora que temos os dados, vamos inserir a linha na tabela
		//primeiro criar lista de objects com os valores que ja obtemos
		
		if(valoresDosParametrosDoMetodo != null & valoresDosParametrosDoMetodo.size() > 0)
		{
			for(int i = 0; i < valoresDosParametrosDoMetodo.size(); i++)
			{
				Object umValorParaParametro = valoresDosParametrosDoMetodo.get(i);
				this.valoresEntradas.add(umValorParaParametro);
				System.out.println("parametro usado:" + umValorParaParametro);
				
			}
		}
		
		if(resultadoEsperado != null)
		{
			this.saidasEsperadas.add(resultadoEsperado);
			
			
		}
		
		if(resultadoObtido != null)
		{
			this.saidasObtidas.add(resultadoObtido);
		}
		
		int quantasColunasDeveriaTerATabela = quantasVariaveisCriadasParaSubstituirLeituraDoTeclado + 
				quantasVariaveisCriadasParaSubstituirEscritaNoTerminal + quantasVariaveisCriadasParaSubstituirEscritaNoTerminal;
		
		if((this.saidasEsperadas.size() + this.saidasObtidas.size() + this.valoresEntradas.size()) >= quantasColunasDeveriaTerATabela)
		{
			//ja temos valores suficientes para adicionar uma nova linha na tabela. Vamos adicionar!!!
			
			//primeiro vamos transformar essa lista em arranjo
			Object[] arranjoValoresParaATabela = new Object[quantasColunasDeveriaTerATabela];
			int percorredorArranjo = 0; 
			for(int j = 0; j < this.valoresEntradas.size(); j++)
			{
				arranjoValoresParaATabela[percorredorArranjo] = this.valoresEntradas.get(j);
				percorredorArranjo = percorredorArranjo + 1;
			}
			
			for(int k = 0; k < this.saidasEsperadas.size(); k++)
			{
				if(percorredorArranjo < arranjoValoresParaATabela.length)
				{
					arranjoValoresParaATabela[percorredorArranjo] = this.saidasEsperadas.get(k);
					percorredorArranjo = percorredorArranjo + 1;
				}
				
				if(percorredorArranjo < arranjoValoresParaATabela.length)
				{
					arranjoValoresParaATabela[percorredorArranjo] = this.saidasObtidas.get(k);
					percorredorArranjo = percorredorArranjo + 1;
				}
			}
			
			//agora vamos finalmente inserir a nova linha na tabela
			modelo.addRow(arranjoValoresParaATabela);
			
			//agora esvaziaremos a lista com os valores ate agora usados
			this.saidasEsperadas.clear();
			this.saidasObtidas.clear();
			this.valoresEntradas.clear();
		}
		
	}
	
	
	private JScrollPane criarPainelComTodosOsResultadosCasosDeTeste()
	{
		JPanel painelComTodosOsResultadosDosTestes = new JPanel(new GridLayout(this.tabelasComResultadosDosTestes.size(), 1));
		for(int i = 0; i < this.tabelasComResultadosDosTestes.size(); i++)
		{
			JTable tabelaDoCasoDeTeste = this.tabelasComResultadosDosTestes.get(i);
			JTableHeader cabecalho = tabelaDoCasoDeTeste.getTableHeader();
			cabecalho.setFont(new Font("Serif", Font.BOLD, 15));  
			JPanel painelUneTabelaECabecalho = new JPanel();
			painelUneTabelaECabecalho.setLayout(new BorderLayout());
			painelUneTabelaECabecalho.add(cabecalho, BorderLayout.NORTH);
			painelUneTabelaECabecalho.add(tabelaDoCasoDeTeste, BorderLayout.CENTER);
			
			painelComTodosOsResultadosDosTestes.add(painelUneTabelaECabecalho);
			
		}
		
		JScrollPane painelScrollTodosOsResultadosDosTestes = new JScrollPane(painelComTodosOsResultadosDosTestes);
		Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
		painelScrollTodosOsResultadosDosTestes.setPreferredSize(new Dimension(d.width - 16, 400));
		return painelScrollTodosOsResultadosDosTestes;
	}
	
	private void colorirTodasAsColunasDeTodasAsTabelasQueForemNecessarias()
	{
		for(int i = 0; i < this.tabelasComResultadosDosTestes.size(); i++)
		{
			JTable umaTabela = this.tabelasComResultadosDosTestes.get(i);
			for(int j = 0; j < umaTabela.getColumnCount(); j++)
			{
				umaTabela.getColumnModel().getColumn(j).setCellRenderer(new ColorRendererTabelaResultadosDosTestes());
			}
		}
	}
	
	@SuppressWarnings("unused")
	@Override
	public void actionPerformed(ActionEvent arg0) 
	{
		SingletonSetaLinguagemEArmazenaResourceBundle conheceLinguagemDoSistema = 
				SingletonSetaLinguagemEArmazenaResourceBundle.getInstance();
		
		Object fonteDoClique = arg0.getSource();
		if(fonteDoClique == this.botaoSalvarTesteCriado)
		{
			Cursor cursorCarregando = new Cursor(Cursor.WAIT_CURSOR);
			this.janelaResultadosDosTestes.setCursor(cursorCarregando);
			if(this.casosDeTeste.isEmpty() != true)
			{
				FachadaParaDadosDeSuitesDeTestes fachadaSalvaSuite = FachadaParaDadosDeSuitesDeTestes.getInstance();
				
				fachadaSalvaSuite.escreverProjetoDeTestesComMain(projetoDeTestesCriadoPeloUsuario);
				this.salvarSeOEstadoDasVariaveisDeveSerMantidoOuNao();
				for(int i = 0; i < casosDeTeste.size(); i++)
				{
					System.out.println("cabecalho metodo:>->->" + casosDeTeste.get(i).getMetodo().getCabecalhoDoMetodo());
					System.out.println("tipo dos parametros de entrada:>->->" + casosDeTeste.get(i).getMetodo().getTiposDosParametrosDeEntrada());
					System.out.println("tipo de retorno do metodo:>->->" + casosDeTeste.get(i).getMetodo().getTipoDeRetorno());
					System.out.println("nomes dos parametros de entrada do metodo:>->->" + casosDeTeste.get(i).getMetodo().getNomesDosParametrosDeEntrada());
					System.out.println("url arquivo java que tem metodo:>->->" + casosDeTeste.get(i).getMetodo().getUrlParaArquivoJavaQueTemOMetodo());
					System.out.println("valores dos parametros:>->->" + casosDeTeste.get(i).getValoresDosParametrosDoMetodo());
					System.out.println("nome classe associada ao caso de teste:>->->" + casosDeTeste.get(i).getNomeClasseAssociadaAoCasoDeTeste());
					System.out.println("endereco projeto>->->" + casosDeTeste.get(i).getEnderecoDoProjetoDaClasseATestar());
					System.out.println(">->->possui retorno?" + casosDeTeste.get(i).getMetodoAssociadoPossuiRetorno());
					System.out.println("saida esperada>->->" + casosDeTeste.get(i).getValorEsperadoDaSaida());
				}
				cursorCarregando = new Cursor(Cursor.DEFAULT_CURSOR);
				this.janelaResultadosDosTestes.setCursor(cursorCarregando);
				
				String tituloTesteSalvo = conheceLinguagemDoSistema.getString("testeSalvoTelaResultadosDosTestesEmTabelaParaTestarMain");
				
				JOptionPane.showMessageDialog(janelaResultadosDosTestes, tituloTesteSalvo);
				
			}
			else
			{
				cursorCarregando = new Cursor(Cursor.DEFAULT_CURSOR);
				this.janelaResultadosDosTestes.setCursor(cursorCarregando);
				
				String tituloTesteVazio = conheceLinguagemDoSistema.getString("testeVazioTelaResultadosDosTestesEmTabelaParaTestarMain");
				
				JOptionPane.showMessageDialog(janelaResultadosDosTestes, tituloTesteVazio);
			}
		}
		else if(fonteDoClique == this.botaoVoltarAoMenuPrincipal)
		{
			this.janelaResultadosDosTestes.getContentPane().setVisible(false);
			this.janelaResultadosDosTestes.getContentPane().invalidate();
			this.janelaResultadosDosTestes.getContentPane().removeAll();
			TelaCriarNovoTesteOuCarregarJaExistente telaMenuPrincipal = new TelaCriarNovoTesteOuCarregarJaExistente(this.janelaResultadosDosTestes);
		}
		
	}
	
	private void salvarSeOEstadoDasVariaveisDeveSerMantidoOuNao()
	{
		FachadaAcessoConfiguracoesSistema escreveEmTxtSeSalvaEstadoDasVariaveis =
											FachadaAcessoConfiguracoesSistema.getInstance();
		escreveEmTxtSeSalvaEstadoDasVariaveis.gravarEmTxtSeOProjetoDeTestesPrecisaManterEstadoDasVariaveis(nomeSuiteDeTestes);
		
	}
}